package org.deng.learn.concurrent.lock;

import java.util.Collection;
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantLock;

/**
 * @author 邓力宾
 * @Desc  来自Java并发编程艺术5.3 重入锁
 * @since 2020/6/4 上午9:04
 */
public class FairAndUnfairDemo {
    private final  static  int THREAD_NUM = 5; // 线程数
    private static CyclicBarrier cyclicBarrier = new CyclicBarrier(THREAD_NUM);

    private static class MyReentrantLock extends ReentrantLock{
        public MyReentrantLock(boolean fair){
            super(fair);
        }

        @Override
        protected Collection<Thread> getQueuedThreads() {
            return super.getQueuedThreads();
        }
    }
    private static class Job extends Thread{
        private MyReentrantLock lock;

        public Job(String name, MyReentrantLock lock){
            super(name);
            this.lock = lock;
        }

        @Override
        public void run() {
            try {
                cyclicBarrier.await(); // 当n个线程都准备好后才继续执行
            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (BrokenBarrierException e) {
                e.printStackTrace();
            }
            // 打印两次
          doSomething();
          doSomething();
        }
        public void doSomething(){
            lock.lock();
            try {
                TimeUnit.MICROSECONDS.sleep(80);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName() + "::" + this.lock.getQueuedThreads());
            lock.unlock();
        }
    }
    public static void testLock(MyReentrantLock lock){
        for(int i  = 0; i < THREAD_NUM; i++){
            new Job((i+1) +"", lock).start();
        }
    }

    public static void main(String[] args) {
        testLock(new MyReentrantLock(true)); //公平锁, 如果把每次不同线程获取到锁定义为1次切换,公平性锁在测试中进行了10次切换,
       // testLock(new MyReentrantLock(false)); // 非公平锁 非公平性锁只有5次切换,

        //公平性锁保证了锁的获取按照FIFO原则,而代价是进行大量的线程切换。非公平性锁虽
        //然可能造成线程“饥饿”,但极少的线程切换,保证了其更大的吞吐量。

    }
}
